<template>
  <FrontSideTable
    dataUrl="/sys/role/getList"
    addUrl="/sys/role/add"
    editUrl="/sys/role/edit"
    deleteUrl="/sys/role/delete"
    tableTitle="角色列表"
    searchHint="根据角色名查找"
    :searchProps="searchProps"
    :columns="columns"
    :form="form"
    :rules="rules"
    @onCreated="onCreated"
    @beforeAdd="handleAdd"
    @beforeEdit="handleEdit"
    @onManage="handleManage"
    manageable>

    <!--  对话框区域  -->
    <template slot="form">
      <el-form-item label="角色名称" prop="name">
        <el-input v-model="form.name" placeholder="输入角色名称"></el-input>
      </el-form-item>
      <el-form-item label="备注">
        <el-input type="textarea" v-model="form.notes" placeholder="输入备注"></el-input>
      </el-form-item>
    </template>

    <template slot="dialog">
      <!--授权对话框-->
      <el-dialog title="角色授权" size="small" v-model="isAuthDialogVisible" :close-on-click-modal="closeOnClickModal">
        <div class="row" v-loading="loadingAuth" element-loading-text="加载授权信息">

          <!--树形菜单选择-->
          <el-card class="card col-xs-5">
            <div slot="header">
              <span class="card-head">菜单列表</span>
            </div>
            <el-tree
              ref="menuTree"
              class="tree-view"
              node-key="id"
              :data="menuTreeData"
              :props="treeProps"
              @node-click="handleNodeClick"
              highlight-current
              show-checkbox
              accordion>
            </el-tree>
          </el-card>

          <!--表格选择区域-->
          <el-card class="card col-xs-6">
            <div slot="header">
              <span class="card-head">功能列表</span>
            </div>
            <SimpleMultipleTable
              ref="functionTable"
              emptyText="请点击左侧菜单,获取权限列表"
              :columns="functionColumns"
              :data="filterFunctionData">
            </SimpleMultipleTable>
          </el-card>
        </div>
        <!--表格选择-->

        <!--对话框按钮-->
        <div slot="footer" class="dialog-footer">
          <el-button @click="isAuthDialogVisible = false">取 消</el-button>
          <el-button type="primary" @click="grantRole" :loading="isGranting">确 定</el-button>
        </div>
      </el-dialog>
    </template>
  </FrontSideTable>
</template>

<script>
  import FrontSideTable from "../../template/FrontSideTable.vue"
  import SimpleMultipleTable from "../../template/SimpleMultipleTable.vue"
  import {doGet,doPost,doDelete} from "../../../assets/js/utils/RequestUtils"
  import {LOADING,COMPLETE} from "../../../store/mutationTypes"
  import {clearFields} from "../../../assets/js/utils/ObjectUtils"
  import {treeOf} from "../../../assets/js/utils/TreeUtils"
  import {ADD,EDIT,DELETE,MANAGE} from "../../../assets/js/enum/FunctionType"
  import {getAuthorizedFunction, hasAuthorizedFunction} from "../../../assets/js/global"

  /** 修改前的角色名称 */
  let oldName = "";

  /** 数据获取及修改的后台地址 */
  const menuDataUrl = "/sys/menu/getList",
    functionDataUrl = "/rel/menuFunction/getMenuFunctionList",
    authMenuUrl = "/sys/role/getRoleMenuList",
    authFunctionUrl = "/sys/role/getRoleFunctionList",
    grantRoleUrl = "/sys/role/grantRole";

  export default {
    name:"RoleManagement",
    data() {
      //角色名校验器
      let nameValidator = (rule, value, callback) => {
        if (oldName === value) {
          callback();
        } else {
          if (this.data.some(item => item.name === value)) {
            callback(new Error("角色名重复"));
          } else {
            callback();
          }
        }
      };

      return {
        //数据
        data: [],

        //菜单数据
        menuData: [],

        //表格数据
        functionData: [],

        //搜索的字段
        searchProps: ["name"],

        /*  树节点属性  */
        treeProps: {
          children: 'children',
          label: 'name'
        },

        /*  默认勾选的树节点  */
        defaultCheckedTreeKeys: new Set(),

        /*  默认勾选的表格节点  */
        defaultCheckedTableKeys: new Set(),

        //表格列
        columns: [
          {prop: "name", label: "角色名"},
          {prop: "notes", label: "备注"}
        ],

        //功能表格列
        functionColumns: [
          {prop:"functionName", label:"功能名称"},
          {prop:"menuName", label:"所属菜单"}
        ],

        //表单对象
        form: {
          name: "",
          notes: ""
        },

        //校验器
        rules: {
          name: [
            {required: true, message: "请输入角色名", trigger: "blur"},
            {validator: nameValidator, trigger: "blur"}
          ]
        },

        //点击外侧不关闭对话框
        closeOnClickModal: false,

        //是否打开授权对话框
        isAuthDialogVisible: false,

        //正在加载授权信息
        loadingAuth: false,

        //是否正在授权
        isGranting: false,

        //当前选择的node
        selectedNodeId: "",

        //当前操作的角色
        currentRoleId: "",
      }
    },
    computed:{
      filterFunctionData() {
        if(this.selectedNodeId) {
          return this.functionData.filter(item => !this.selectedNodeId || item.menuId === this.selectedNodeId)
        }else {
          return [];
        }
      },
      menuTreeData() {
        return treeOf(this.menuData);
      }
    },
    methods: {
      handleNodeClick(data) {
        this.selectedNodeId = data.id;
      },
      handleAdd() {
        oldName = "";
        clearFields(this.form);
      },
      handleEdit(data) {
        oldName = data.name;
        this.form = {...data};
      },
      handleManage(data) {
        this.currentRoleId = data.id;
        this.loadingAuth = true;
        this.isAuthDialogVisible = true;
        this.defaultCheckedTreeKeys.clear();
        this.defaultCheckedTableKeys.clear();
        this.fetchData(data.id);
      },
      //授权给角色
      grantRole() {
        this.isGranting = true;
        doPost(grantRoleUrl, {
          data:{
            roleId:this.currentRoleId,
            menuIds:this.$refs["menuTree"].getCheckedKeys(),
            menuFunctionIds:this.$refs["functionTable"].getCheckedKeys(this.functionData)
          },
          menuFunctionId:getAuthorizedFunction(this, MANAGE),
          component: this
        })
          .then(response => this.$message({message: response.message, type: response.status.toLowerCase()}))
          .finally(()=>{
            this.isGranting = false;
            this.isAuthDialogVisible = false;
          });
      },
      //根据数据自动勾选表格
      setTableSelection() {
        //先设定预先勾选的项
        this.functionData.forEach(item=> item.isChecked = this.defaultCheckedTableKeys.has(item.id));
        //勾选表格
        if(this.$refs["functionTable"] !== undefined) {
          this.$refs["functionTable"].checkDefaultRows();
        }
      },
      setTreeSelection() {
        if(this.$refs["menuTree"] !==undefined) {
          this.$refs["menuTree"].setCheckedKeys([...this.defaultCheckedTreeKeys]);
        }
      },
      onCreated(data) {
        this.data = data;
      },
      //①加载菜单数据，然后加载功能数据
      fetchData(roleId) {
        doGet(menuDataUrl, {component:this})
          .then(response=>{
            this.menuData = response;
            this.fetchFunctionData(roleId)
          })
      },
      //②加载功能数据后关闭模态
      fetchFunctionData(roleId) {
        doGet(functionDataUrl, {component:this})
          .then(response=>{
            this.functionData = response;
            this.fetchAuth(roleId)
          })
      },
      //③加载完菜单授权信息后，继续加载功能授权信息
      fetchAuth(roleId) {
        doGet(authMenuUrl,{
          data:{roleId:roleId},
          component:this
        })
          .then(response=>{
            this.defaultCheckedTreeKeys = new Set(response.filter(item=>!this.menuData.some(i=>i.parentId === item.menuId)).map(item=>item.menuId));
            this.setTreeSelection();
            this.fetchAuthFunction(roleId);
          })
      },
      //④加载完授权信息后，关闭加载模态
      fetchAuthFunction(roleId) {
        doGet(authFunctionUrl, {
          data:{roleId:roleId},
          component:this
        })
          .then(response=>{
            //勾选默认的行数据
            response.forEach(item=>this.defaultCheckedTableKeys.add(item.menuFunctionId));
            this.setTableSelection();
          })
          .finally(()=>this.loadingAuth = false);
      }
    },

    components: {FrontSideTable, SimpleMultipleTable}
  }
</script>

<style scoped>
  .tree-view {
    border: 0;
  }
  .card {
    margin-left: 15px;
    padding: 5px 5px 5px 5px;
  }
  .card-head {
    font-size: 1.2em;
    font-weight: bold;
  }
</style>



// WEBPACK FOOTER //
// RoleManagement.vue?d4f2e93e
